package nccloud.web.workflow.approvalcenter.action;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import itf.approvecenter.util.DataExchangeBean;
import itf.approvecenter.util.InteractiveExceptionContext;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import nc.itf.uap.pf.IWorkflowDefine;
import nc.vo.ml.NCLangRes4VoTransl;
import nc.vo.pub.AggregatedValueObject;
import nc.vo.pub.BusinessException;
import nc.vo.pub.billtype2.Billtype2VO;
import nc.vo.pub.lang.UFBoolean;
import nc.vo.pub.workflownote.WorkflownoteVO;
import nc.vo.wfengine.definition.WorkflowTypeEnum;
import nccloud.base.exception.ExceptionUtils;
import nccloud.commons.lang.StringUtils;
import nccloud.framework.mob.action.itf.IMobileAction;
import nccloud.framework.mob.container.IMobRequest;
import nccloud.framework.mob.container.MobClientInfo;
import nccloud.framework.service.ServiceLocator;
import nccloud.framework.web.action.itf.ICommonAction;
import nccloud.framework.web.container.ClientInfo;
import nccloud.framework.web.container.IRequest;
import nccloud.framework.web.container.SessionContext;
import nccloud.itf.uap.pf.IApproveBusiHandler;
import nccloud.itf.uap.pf.NCCWorkFlowService;
import nccloud.pubitf.platform.approve.AbstractApproveBusiHandlerImpl;
import nccloud.putitf.riart.billtype.IBilltypeService;
import nccloud.web.workflow.approve.util.ApproveWorkitemAssistor;
import nccloud.web.workflow.approve.util.NCCFlowUtils;
import nccloud.web.workflow.approve.util.NCCMsgContext;


public class ApprovePassAction
  implements ICommonAction, IMobileAction
{
  Set<String> busiexceptionCodeSet = new HashSet();
  
  private String from_terminal = "";
  
  public Object doAction(IRequest request) {
    String jsonStr = request.read();
    String cuserid = SessionContext.getInstance().getClientInfo().getUserid();
    return doApprovePass(jsonStr, cuserid, false);
  }
  
  public Object doAction(IMobRequest req) {
    String jsonStr = req.read();
    String cuserid = (new MobClientInfo()).getUserid();
    ClientInfo clientInfo = new ClientInfo();
    
    this.from_terminal = "mobile";
    clientInfo.setUserid(cuserid);
    clientInfo.setPk_group((new MobClientInfo()).getPk_group());
    clientInfo.setUsercode((new MobClientInfo()).getUserCode());
    clientInfo.setLangcode((new MobClientInfo()).getLangCode());
    SessionContext.getInstance().setClientInfo(clientInfo);
    return doApprovePass(jsonStr, cuserid, true);
  }
  
  public String getCheckNotePulsApproveResult(String checknote, PfChecknoteEnum check) {
    if (check == PfChecknoteEnum.PASS) {
      
      checknote = checknote + UFBoolean.valueOf(true).toString();
    } else if (check == PfChecknoteEnum.NOPASS) {
      
      checknote = checknote + UFBoolean.valueOf(false).toString();
    } else if (check == PfChecknoteEnum.REJECT) {
      
      checknote = checknote + "R";
    } 
    return checknote;
  }
  
  private AggregatedValueObject getBillVo(boolean isMobile, String pk_checkflow, String billTypeOrTransType, String billId) {
    NCCWorkFlowService nccWorkFlowService = (NCCWorkFlowService)ServiceLocator.find(NCCWorkFlowService.class);
    AggregatedValueObject billvo = null;
    try {
      if (!isMobile)
      {
        if (StringUtils.isNotBlank(pk_checkflow)) {
          String pk_group = nccWorkFlowService.getGroupByPKCheckFlow(pk_checkflow);
          if (StringUtils.isNotBlank(pk_group)) {
            SessionContext.getInstance().getClientInfo().setPk_group(pk_group);
          }
        } 
      }
      
      billvo = nccWorkFlowService.mobileAppUtilForQueryBillEntity(billTypeOrTransType, billId);
    } catch (BusinessException e) {
      ExceptionUtils.wrapBusinessException(NCLangRes4VoTransl.getNCLangRes().getStrByID("0020nccloud_0", "0ncc0020001-0430"));
    } 
    
    return billvo;
  }
  
  private WorkflownoteVO getWorkflownoteVO(String billTypeOrTransType, String billId, String pk_checkflow, boolean isTrack, HashMap<Object, Object> hmPfExParams, String jsonStr) {
    WorkflownoteVO note = null;
    NCCWorkFlowService nccWorkFlowService = (NCCWorkFlowService)ServiceLocator.find(NCCWorkFlowService.class);
    try {
      note = nccWorkFlowService.checkWorkflowActions(billTypeOrTransType, billId, pk_checkflow);
      if (note == null) {
        hmPfExParams.put("notechecked", "notechecked");
      } else {
        note.setTrack(isTrack);
        hmPfExParams.put("worknote", note);
      } 
      NCCFlowUtils.checkIsCopySend(note, JSON.parseObject(jsonStr));
    } catch (Exception e) {
      ExceptionUtils.wrapException(e);
    } 
    return note;
  }
  
  private void setApproveCa(JSONObject json2, WorkflownoteVO note) {
    Boolean isNeedCaSign = json2.getBoolean("isNeedCaSign");
    if (isNeedCaSign != null && isNeedCaSign.booleanValue()) {
      String sn = json2.getString("sn");
      String signStr = json2.getString("signStr");
      ApproveWorkitemAssistor.nccSign(note, sn, signStr);
    }
  }
  
  private Object doApprovePass(String jsonStr, String cuserid, boolean isMobile) {
    JSONObject json2 = JSON.parseObject(jsonStr);
    boolean isTrack = false;
    if (json2.get("isTrack") != null) {
      isTrack = json2.getBoolean("isTrack").booleanValue();
    }
    String from_terminal = json2.getString("from_terminal");
    if (!StringUtils.isBlank(from_terminal)) {
      this.from_terminal = from_terminal;
    } else {
      this.from_terminal = "pc";
    } 
    HashMap<Object, Object> hmPfExParams = new HashMap<Object, Object>();
    
    DataExchangeBean bean = new DataExchangeBean();
    bean.setCode("200");
    NCCMsgContext nccMsg = new NCCMsgContext(jsonStr);
    Map<String, Object> paramInfoMap = nccMsg.getMsgINfoContext();
    
    String[] flowParameterArray = { "billtype", "billid", "pk_checkflow" };
    
    if (NCCFlowUtils.isFlowParameterArrayNull(flowParameterArray, paramInfoMap)) {
      return NCCFlowUtils.exchangeDataMsg(bean, "500", 
          NCLangRes4VoTransl.getNCLangRes().getStrByID("0020nccloud_0", "0ncc0020001-0428"));
    }
    
    String billTypeOrTransType = paramInfoMap.get("billtype").toString();
    String billId = paramInfoMap.get("billid").toString();
    String pk_checkflow = paramInfoMap.get("pk_checkflow").toString();
    String check_note = json2.getString("check_note");
    String skipcodes = json2.getString("skipCodes");
    
    NCCFlowUtils.checkIsExistMessage(billTypeOrTransType, billId, cuserid);
    
    String paramBusiCodes = null;
    if (paramInfoMap.get("skipCodes") != null && 
      !"[]".equals(paramInfoMap.get("skipCodes").toString()))
    {
      
      paramBusiCodes = paramInfoMap.get("skipCodes").toString().substring(1, paramInfoMap.get("skipCodes").toString().length() - 1).replace("\"", "");
    }
    
    WorkflownoteVO note = getWorkflownoteVO(billTypeOrTransType, billId, pk_checkflow, isTrack, hmPfExParams, jsonStr);
    
    note.setApproveresult(UFBoolean.TRUE.toString());
    if (StringUtils.isEmpty(check_note)) {
      check_note = NCCFlowUtils.getIndividualCheckNote(PfChecknoteEnum.PASS, cuserid);
      
      if (StringUtils.isEmpty(check_note)) {
        ExceptionUtils.wrapBusinessException(NCLangRes4VoTransl.getNCLangRes().getStrByID("0020nccloud_0", "0ncc0020001-0523"));
      } else {
        note.setChecknote(check_note);
      } 
    } else {
      note.setChecknote(check_note);
    }
    
    if (paramInfoMap.get("isAssgin") == null || (paramInfoMap
      .get("isAssgin") != null && !((Boolean)paramInfoMap.get("isAssgin")).booleanValue())) {
      
      JSONObject assginre = (new AssginUtil()).getAssginResult(note);
      
      if (assginre != null) {
        return assginre;
      }
    } 
    
    NCCWorkFlowService nccWorkFlowService = (NCCWorkFlowService)ServiceLocator.find(NCCWorkFlowService.class);
    String billtype2RegistClass = "";
    AggregatedValueObject billvo = getBillVo(isMobile, pk_checkflow, billTypeOrTransType, billId);
    
    try {
      String msgError = checkApprovePoint(note);
      if (StringUtils.isNotBlank(msgError)) {
        
        String msg = NCLangRes4VoTransl.getNCLangRes().getStrByID("0020nccloud_0", "0ncc0020001-0529");
        throw new BusinessException(msg);
      } 
      
      IBilltypeService billTypeServiceImpl = (IBilltypeService)ServiceLocator.find(IBilltypeService.class);
      String billType = nccWorkFlowService.getRealBilltype(billTypeOrTransType);
      
      if (billTypeServiceImpl.queryBilltypeVOsFromCache(billType, 25) != null && billTypeServiceImpl
        .queryBilltypeVOsFromCache(billType, 25).size() > 0)
      {
        billtype2RegistClass = ((Billtype2VO)billTypeServiceImpl.queryBilltypeVOsFromCache(billType, 25).get(0)).getClassname();
      }
      
      if (!"".equals(billtype2RegistClass) && billtype2RegistClass != null) {
        bean = beforeApproveCheck(billtype2RegistClass, billvo, billTypeOrTransType, billId, bean, from_terminal, skipcodes, note);
        
        if (bean != null && StringUtils.isNotEmpty(bean.getCode()) && !"200".equals(bean.getCode())) {
          return bean;
        }
      } 
    } catch (Exception e1) {
      ExceptionUtils.wrapException(e1);
      return NCCFlowUtils.exchangeDataMsg(bean, "500", 
          NCLangRes4VoTransl.getNCLangRes().getStrByID("0020nccloud_0", "0ncc0020001-0431") + e1
          .getMessage());
    } 
    
    try {
      nccWorkFlowService.setAssignInfos(paramInfoMap, note);
      
      NCCFlowUtils.handleAttrfiles(json2, note);
      
      setApproveCa(json2, note);
      
      List<Map<String, Object>> paraMapList = new ArrayList<Map<String, Object>>();
      Map paraMap = new HashMap();
      paraMap.put("NCCFlowParamter", "NCCloud");
      paraMap.put("from_terminal", this.from_terminal);
      if (paramBusiCodes != null) {
        paraMap.put("NCC_BusiCodes", paramBusiCodes);
      }
      paraMapList.add(paraMap);
      
      if (WorkflowTypeEnum.fromIntValue(note.getWorkflow_type().intValue()).equals(WorkflowTypeEnum.Approveflow) || 
        WorkflowTypeEnum.fromIntValue(note.getWorkflow_type().intValue()).equals(WorkflowTypeEnum.SubApproveflow)) {
        
        bean = ApproveOrSignalActionUtil.processAction("APPROVE", billTypeOrTransType, note, billvo, paraMapList, null, billtype2RegistClass);
      } else {
        
        bean = ApproveOrSignalActionUtil.processAction("SIGNAL", billTypeOrTransType, note, billvo, paraMapList, null, billtype2RegistClass);
      }
    
    }
    catch (BusinessException e) {
      ExceptionUtils.wrapException(e);
    }
    return JSON.toJSON(bean);
  }
  
  public DataExchangeBean beforeApproveCheck(String billtype2RegistClass, AggregatedValueObject billvo, String billTypeOrTransType, String billId, DataExchangeBean bean, String from_terminal, String skipcodes, WorkflownoteVO note) throws BusinessException {
    try {
      Class clazz = Class.forName(billtype2RegistClass);
      
      if (AbstractApproveBusiHandlerImpl.class.isAssignableFrom(clazz)) {
        
        AbstractApproveBusiHandlerImpl approveBusiClass = (AbstractApproveBusiHandlerImpl)clazz.newInstance();
        
        InteractiveExceptionContext context = new InteractiveExceptionContext();
        context.setBilltype(billTypeOrTransType);
        context.setArgsList(note.getApplicationArgs());
        context.setBillId(billId);
        context.setFrom_terminal(from_terminal);
        if (StringUtils.isNotEmpty(skipcodes) && !"[]".equals(skipcodes)) {
          context.setSkipcodes(String.valueOf(skipcodes).substring(1, skipcodes.length() - 1).split(","));
        } else {
          context.setSkipcodes(null);
        }
        context.setBillVos(new AggregatedValueObject[] { billvo });
        
        List<String> otlist = new ArrayList<String>();
        
        otlist.add("am");
        otlist.add("sp");
        
        otlist.add("pu");
        otlist.add("me");
        otlist.add("scmpub");
        otlist.add("ic");
        if (approveBusiClass.checkBeforeIsRunMethodParam(context) != null && otlist
          .contains(approveBusiClass.checkBeforeIsRunMethodParam(context).getCode())) {
          bean = approveBusiClass.checkBeforeApproveWithArgList(context);
          if (bean != null && StringUtils.isNotEmpty(bean.getCode()) && !"200".equals(bean.getCode())) {
            return bean;
          }
        } 
        bean = approveBusiClass.checkBeforeApprove(billTypeOrTransType, billId, billvo);
        if (bean != null && StringUtils.isNotEmpty(bean.getCode()) && !"200".equals(bean.getCode())) {
          return bean;
        }
      } else {
        IApproveBusiHandler approveBusiAction = (IApproveBusiHandler)clazz.newInstance();
        bean = approveBusiAction.checkBeforeApprove(billTypeOrTransType, billId, billvo);
        if (bean != null && StringUtils.isNotEmpty(bean.getCode()) && !"200".equals(bean.getCode())) {
          return bean;
        }
      } 
    } catch (Exception e) {
      throw new BusinessException(e);
    } 
    return null;
  }
  
  private String checkApprovePoint(WorkflownoteVO note) throws BusinessException {
    IWorkflowDefine workflowDefine = (IWorkflowDefine)ServiceLocator.find(IWorkflowDefine.class);
    return workflowDefine.checkApprovePointByWorkNote(note, "Y");
  }
}